package org.geekbang.thinking.in.spring.conversion.ioc;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

@Component
public class SpringIoc implements DisposableBean {
    // Hollywood Principle 好莱坞原则： never call methods of a controller
    // 不要来找我们（资源），我们会来找你（模块）。

    /**
     * Spring AOP 总览
     * 1.知识储备:基础、基础，还是基础!
     * 2.AOP 引入:OOP 存在哪些局限性?
     * 3.AOP 常见使用场景
     * 4.AOP 概念:Aspect、Join Point 和 Advice 等术语应该如何理解?
     * 5.Java AOP 设计模式:代理、判断和拦截器模式
     * 6.Java AOP 代理模式(Proxy):Java 静态代理和动态代理的区别是什么?
     * 7.Java AOP 判断模式(Predicate):如何筛选 Join Point?
     * 8.Java AOP 拦截器模式(Interceptor):拦截执行分别代表什么?
     * 9.Spring AOP 功能概述:核心特性、编程模型和使用限制
     * 10.Spring AOP 编程模型:注解驱动、XML 配置驱动和底层 API
     * 11.Spring AOP 设计目标:Spring AOP 与 AOP 框架之间的关系是竞争还是互补?
     * 12.Spring AOP Advice 类型:Spring AOP 丰富了哪些 AOP Advice 呢?
     * 13.Spring AOP 代理实现:为什么 Spring Framework 选择三种不同 AOP 实现?
     * 14.JDK 动态代理:为什么 Proxy.newProxyInstance 会生成新的字节码?
     * 15.CGLIB 动态代理:为什么 Java 动态代理无法满足 AOP 的需要?
     * 16.Aspecty 代理代理:为什么 Spring 推荐 Aspecty 注解?
     * 17.AspectJ基础:Aspect、Join Points、Pointcuts 和 Advice 语法和特性
     * 18.Aspecty 注解驱动:注解能完全替代 AspectJ 语言吗?
     * 19.面试题精选
     *
     */


    // Java 基础 ： Java ClassLoading 、 Java动态代理、 Java 反射、 字节码框架：ASM、CGLIB
    // OOP ： 继承、多态、封装、抽象、接口
    // 双亲委派机制

    // Spring 核心基础：Spring IOC、 Spring Bean生命周期、 Spring 配置元信息、 Spring 事件、 Spring 注解

    // ==================================================================================================

    /**
     * Spring IOC
     *  控制反转：是一种决定容器如何装配组件的模式。定义、创建、销毁
     *  IoC容器：背后的思想正是好莱坞原则，即所有的组件都要被动接受容器的控制
     *  Spring 容器初始化
     *      1、从 XML 文件、Java 类或其他地方加载配置元数据。
     *      2、通过 BeanFactoryPostProcessor 对配置元数据进行一轮处理。
     *      3、初始化 Bean 实例，并根据给定的依赖关系组装对象。
     *      4、通过 BeanPostProcessor 对 Bean 进行处理，期间还会触发 Bean 被构造后的回调方法。
     */

    /**
     * Java ClassLoading
     * URLClassLoader
     */
    private String name;
    private String msg;


    public String sayHello() {
        System.out.println("Hello World!");
        return "Hello World!";
    }


    public SpringIoc() {
    }

    public SpringIoc(String name, String msg) {
        this.name = name;
        this.msg = msg;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    @Override
    public void destroy() throws Exception {
        System.out.println("SpringIoc destroy");
    }

    @PreDestroy
    public void shutdown() {
        System.out.println("SpringIoc shutdown");
    }

    public void close() {
        System.out.println("SpringIoc close");
    }

    /**
     * Returns a string representation of the object.
     *
     * @return a string representation of the object.
     * @apiNote In general, the
     * {@code toString} method returns a string that
     * "textually represents" this object. The result should
     * be a concise but informative representation that is easy for a
     * person to read.
     * It is recommended that all subclasses override this method.
     * The string output is not necessarily stable over time or across
     * JVM invocations.
     * @implSpec The {@code toString} method for class {@code Object}
     * returns a string consisting of the name of the class of which the
     * object is an instance, the at-sign character `{@code @}', and
     * the unsigned hexadecimal representation of the hash code of the
     * object. In other words, this method returns a string equal to the
     * value of:
     * <blockquote>
     * <pre>
     * getClass().getName() + '@' + Integer.toHexString(hashCode())
     * </pre></blockquote>
     */
    @Override
    public String toString() {
        return super.toString();
    }
}
